// 定义Shader在Unity编辑器中的路径为 "Custom/RimAndAlpha"
Shader "Custom/RimAndAlpha"
{
    // 属性块，定义所有希望在材质编辑器中调整的参数
    Properties
    {
        _MainTex("基础贴图 (MainTex)", 2D) = "white" {} // 模型的贴图
        _Color("模型颜色与透明度 (Color & Alpha)", Color) = (1, 1, 1, 1) // 模型的颜色，其Alpha通道控制整体透明度

        [Header(Rim Light Settings)] // 在Inspector中显示一个标题，方便区分
        _RimColor("边缘光颜色 (Rim Color)", Color) = (1, 1, 0, 1) // 边缘光的颜色
        _RimPower("边缘光范围 (Rim Power)", Range(0.1, 10.0)) = 2.0 // 控制边缘光的范围/厚度，值越大边缘越窄
        _RimIntensity("边缘光强度 (Rim Intensity)", Range(0.0, 5.0)) = 1.0 // 控制边缘光的亮度
    }

    SubShader
    {
        // 标签块，对于需要透明效果的Shader，必须正确设置
        // "Queue"="Transparent" 告诉Unity这个物体应该在所有不透明物体之后渲染
        // "RenderType"="Transparent" 用于着色器替换等高级功能
        Tags { "Queue"="Transparent" "RenderType"="Transparent" }

        Pass
        {
            // --- 透明效果的关键设置 ---
            Blend SrcAlpha OneMinusSrcAlpha  // 启用标准的Alpha混合模式
            ZWrite Off                      // 关闭深度写入。透明物体通常不写入深度缓冲，以避免遮挡后面的物体
            // Cull Off                     // 如果需要双面都显示，可以取消这一行的注释

            CGPROGRAM
            // 定义顶点着色器函数名为vert
            #pragma vertex vert
            // 定义片元着色器函数名为frag
            #pragma fragment frag

            // 引入Unity的内置变量和函数库
            #include "UnityCG.cginc"

            // 从Properties块中声明对应的变量
            sampler2D _MainTex;
            float4 _MainTex_ST; // 用于纹理缩放和偏移
            fixed4 _Color;
            fixed4 _RimColor;
            float _RimPower;
            float _RimIntensity;

            // 定义顶点着色器的输入结构体（从模型传入的数据）
            struct appdata
            {
                float4 vertex : POSITION;   // 顶点位置
                float3 normal : NORMAL;     // 顶点法线
                float2 uv : TEXCOORD0;      // UV坐标
            };

            // 定义顶点着色器的输出结构体（传递给片元着色器的数据）
            struct v2f
            {
                float4 vertex : SV_POSITION;       // 屏幕裁剪空间中的顶点位置
                float2 uv : TEXCOORD0;             // UV坐标
                float3 worldNormal : TEXCOORD1;    // 世界空间中的法线方向
                float3 viewDir : TEXCOORD2;        // 世界空间中的视线方向
            };

            // 顶点着色器函数
            v2f vert(appdata v)
            {
                v2f o;
                // 将模型的本地顶点坐标转换到屏幕裁剪空间坐标
                o.vertex = UnityObjectToClipPos(v.vertex);
                // 转换UV坐标（应用贴图的Tiling和Offset）
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                // 将法线从模型空间转换到世界空间
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                // 获取顶点的世界坐标
                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                // 计算从顶点指向摄像机的视线方向（并归一化）
                o.viewDir = normalize(_WorldSpaceCameraPos.xyz - worldPos);
                return o;

            }

            // 片元着色器函数
            fixed4 frag(v2f i) : SV_Target
            {
                // 1. 获取模型的基础颜色
                // 采样贴图颜色，并与我们设定的_Color属性相乘
                fixed4 baseColor = tex2D(_MainTex, i.uv) * _Color;

                // 2. 计算边缘光
                // 法线和视线方向在传递过程中可能不是单位长度，所以在这里重新归一化以保证计算准确
                float3 normal = normalize(i.worldNormal);
                float3 viewDir = normalize(i.viewDir);
                // 计算法线和视线方向的点积。saturate函数将结果限制在[0, 1]范围
                float dotProduct = saturate(dot(normal, viewDir));
                // 用1减去点积，得到边缘因子。在边缘处（点积为0），因子为1；在中心处（点积为1），因子为0
                float rimFactor = 1.0 - dotProduct;
                // 使用pow函数，通过_RimPower来控制边缘的衰减速度（即边缘光的厚度）
                rimFactor = pow(rimFactor, _RimPower);
                // 最终的边缘光颜色 = 边缘光属性色 * 边缘因子 * 边缘光强度
                fixed3 rimColor = _RimColor.rgb * rimFactor * _RimIntensity;

                // 3. 组合最终颜色
                // 将基础颜色的RGB通道与计算出的边缘光颜色相加
                fixed3 finalColor = baseColor.rgb + rimColor;
                // 最终输出的Alpha值取自基础颜色（_Color的Alpha通道）
                fixed finalAlpha = baseColor.a;

                // 返回最终的颜色和透明度
                return fixed4(finalColor, finalAlpha);
            }
            ENDCG
        }
    }
    // 为不支持高级Shader的旧设备提供一个回退方案
    FallBack "Transparent/VertexLit"
}